#include "OpenglAppFramework/inc/PlugIn/Material.h"
#include "OpenglAppFramework/inc/Shader.h"
#include "OpenglAppFramework/inc/SceneConfig.h"
#include "OpenglAppFramework/inc/Config.h"
#include "OpenglAppFramework/inc/Utils.h"
#include "glad/inc/glad.h"

#include <iostream>

Material::Material(const std::string& name) :
    PlugIn(name, PlugInType::Material),
    material_color(0.8f, 0.8f, 0.8f),   // 默认灰色
    specula_color(0.06, 0.06, 0.06) {      // 默认材质只有漫反射，没有高光
    shininess = 1.0;
}

Material::~Material() {}

void Material::setTexturePath(const std::string& tex_path, 
    const std::string& light_tex_path, const std::string& norm_tex_path, const std::string& shicha_tex_path) {
    image.file_path = tex_path;
    light_map.file_path = light_tex_path;
    norm_map.file_path = norm_tex_path;
    shicha_map.file_path = shicha_tex_path;
}

int Material::setConfigData(const nlohmann::json& data) {
    // data内容：{color, image, specula_color, normal_texture, shininess, high_light_texture, normal_texture}
    if(data.find("color") != data.end()) {
        json2Vec3(data["color"], material_color);
    }
    if(data.find("image") != data.end()) {
        image.file_path = OpenglAppConfig::resource_dir + '/' + std::string(data["image"]);
    }
    if(data.find("specula_color") != data.end()) {
        json2Vec3(data["specula_color"], specula_color);
    }
    if(data.find("shininess") != data.end()) {
        shininess = data["shininess"].get<float>();
    }
    if(data.find("high_light_texture") != data.end()) {
        light_map.file_path = OpenglAppConfig::resource_dir + '/' + std::string(data["image"]);
    }
    if(data.find("normal_texture") != data.end()) {
        norm_map.file_path = OpenglAppConfig::resource_dir + '/' + std::string(data["image"]);
    }

    return 0;
}

int Material::init() {
    if(image.file_path.empty() == false) {
        if(image.texture.loadAndBind(image.file_path) != 0) {
            return -1;
        }
        m_obj->textureManger().setTextureName(image.texture.getTextureId(), "material.tex_unit_id");
    }
    if(light_map.file_path.empty() == false) {
        if(light_map.texture.loadAndBind(light_map.file_path) != 0) {
            return -1;
        }
        m_obj->textureManger().setTextureName(light_map.texture.getTextureId(), "material.light_tex_unit_id");
    }
    if(norm_map.file_path.empty() == false) {
        if(norm_map.texture.loadAndBind(norm_map.file_path) != 0) {
            return -1;
        }
        m_obj->textureManger().setTextureName(norm_map.texture.getTextureId(), "material.norm_tex_unit_id");
    }
    if(shicha_map.file_path.empty() == false) {
        if(shicha_map.texture.loadAndBind(shicha_map.file_path) != 0) {
            return -1;
        }
        m_obj->textureManger().setTextureName(shicha_map.texture.getTextureId(), "material.shicha_tex_unit_id");
    }
    return 0;
}

void Material::destroy() {
    // 貌似opengl texture对象不用释放???
}

void Material::uploadShaderData(Shader* shader) {
    // 贴图纹理
    bool flag = image.texture.isLoaded() ? true : false;
    shader->setBool("material.has_tex", flag);
    // 法线纹理
    flag = norm_map.texture.isLoaded() ? true : false;
    shader->setBool("material.has_norm_tex", flag);
    // 光照纹理
    flag = light_map.texture.isLoaded() ? true : false;
    shader->setBool("material.has_light_tex", flag);

    shader->setVec3("material.material_color", material_color);
    shader->setVec3("material.specular_color", specula_color);
    shader->setFloat("material.shininess", shininess);
}